#include "MainVeinFinder.h"
#include "VeinWalker.h"
#include "RunFinder.h"
#include "Screen.h"
#include "Debug.h"

#include <iostream>
#include <vector>



void MainVeinFinder::FindMainVein(const VeinWalker::Criteria *pCrit, S32 nVeinForcedMain)
//                                bool bShowProgress)
{
	RunFinder<Image> rf(m_pImage);
	S32 nRow;
	F64 nCol;
	std::vector<Run> runVector;
	S32 nRunsCount = rf.GetRunsForRow(nRow = m_pImage->GetHeight() / 2, 255, &runVector);
	F64 nBestScore = 0.0;
	Debug::g_bAtMainVein = true;
	if (nVeinForcedMain < -1) 
		abort();
	S32 nStartVein = nVeinForcedMain == -1 ? 0 : nVeinForcedMain;
	S32 nEndVein = nVeinForcedMain == -1 ? nRunsCount : nVeinForcedMain + 1;
	for(S32 i = nStartVein; i < nEndVein; ++i) {
		Debug::Stream() << "FindMainVein - checking " << i + 1 << " of " << nRunsCount << std::endl;
		Point<F64> ptSpawn(nRow, nCol = runVector[i].m_nStartPos + runVector[i].m_nLength / 2);
		VeinWalker::Info info;
		F64 nScore = GetMainVeinInfoAndScoreFromPoint(pCrit, ptSpawn, &info);
		if (nScore > nBestScore) {
			nBestScore = nScore;
			m_veinInfo = info;
			m_searchStartPoint.Set(nRow, nCol);
			Debug::Stream() << "FindMainVein - New winner" << std::endl;
		} 
	}
	Debug::g_bAtMainVein = false;
}

void MainVeinFinder::FindMainVeinFromPoint(const VeinWalker::Criteria *pCrit, Point<F64> ptSpawn)
{
	Debug::g_bAtMainVein = true;
	GetMainVeinInfoAndScoreFromPoint(pCrit, ptSpawn, &m_veinInfo);
	m_searchStartPoint = ptSpawn;
	Debug::g_bAtMainVein = false;
}

F64 MainVeinFinder::GetMainVeinInfoAndScoreFromPoint(const VeinWalker::Criteria *pCrit, Point<F64> ptSpawn,
                                                     VeinWalker::Info *pInfo)
{
	VeinWalker vw1 = VeinWalker::VeinWalker(m_pImage, ptSpawn.Row(), ptSpawn.Col(), 0, pCrit);
	vw1.GetVeinInfo(false, pInfo);
	F64 nScore = CalculateMainVeinScore(m_pImage->GetWidth(), m_pImage->GetHeight(), pInfo->Dist2(),
	                                    pInfo->m_nAverageThickness);
	return nScore;
}

/*static*/ F64 MainVeinFinder::CalculateMainVeinScore(F64 nImageWidth, F64 nImageHeight, 
                                                  F64 nDist2, F64 nThickness)
{
	nDist2 = nDist2 / (nImageWidth * nImageWidth + nImageHeight * nImageHeight);
	nThickness = nThickness * nThickness / (nImageWidth * nImageWidth + nImageHeight * nImageHeight);
	
	return nThickness * 5 + nDist2;
}

